package team.nmsg.ge.system.util;

import org.hibernate.FlushMode;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.orm.hibernate4.SessionFactoryUtils;
import org.springframework.orm.hibernate4.SessionHolder;
import org.springframework.transaction.support.TransactionSynchronizationManager;

/**
 * 由于在http请求线程之外,openssessioninviewfilter不起作用，
 * 导致线程没有绑定session，这个类就是为了解决此问题。
 * 自己管理Hibernate Session的Runnable。
 */
public abstract class SysTxSessionRunnable implements Runnable {
	
	@Override
	public final void run() {
		SessionFactory sessionFactory = (SessionFactory) SysSpringContext.getAppContext().getBean("sessionFactory");
		boolean participate = bindHibernateSessionToThread(sessionFactory);
		try {
			sysRun();
		} finally {
			closeHibernateSessionFromThread(participate, sessionFactory);
		}
	}

	public abstract void sysRun();

	public static boolean bindHibernateSessionToThread( SessionFactory sessionFactory) {
		if (TransactionSynchronizationManager.hasResource(sessionFactory)) {
			return true;
		} else {
			Session session = sessionFactory.openSession();
			session.setFlushMode(FlushMode.MANUAL);
			SessionHolder sessionHolder = new SessionHolder(session);
			TransactionSynchronizationManager.bindResource(sessionFactory, sessionHolder);
		}
		return false;
	}

	public static void closeHibernateSessionFromThread(boolean participate, Object sessionFactory) {
		if (!participate) {
			SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.unbindResource(sessionFactory);
			SessionFactoryUtils.closeSession(sessionHolder.getSession());
		}
	}

}